perm filename RECAUX.SAI[NEW,AIL] blob
sn#408222 filedate 1979-01-08 generic text, type T, neo UTF8
COMMENT Auxilliary record service routines.
Modified for new-style record descriptors.
;
ENTRY;
BEGIN "RECAUX"
REQUIRE "ABBREV.SAI" SOURCE!FILE;
REQUIRE "MACROS.SAI" SOURCE!FILE;
REQUIRE "STCODE.DEF" SOURCE!FILE;
REQUIRE "SYS:RECORD.DEF" SOURCE!FILE;
DEFINE RPTR="RECORD!POINTER";
! rectype, $rectype, cvrts, bldnrc, chkrec, cpyrec, etc;
INTERNAL INTEGER SIMPLE PROCEDURE RECLEN(RPTR(ANY!CLASS) R);
START!CODE
LABEL XIT;
SKIPN 1,R;
JRST XIT;
MOVE 1,(1); ! get the descriptor;
MOVE 1,3(1); ! the size field therefrom;
XIT: END;
INTERNAL INTEGER SIMPLE PROCEDURE RECTYPE(RPTR (ANY!CLASS) R);
START!CODE
SKIPE 1,R;
HRRZ 1,(1);
END;
INTERNAL RPTR($CLASS) SIMPLE PROCEDURE $RECTYPE(RPTR(ANY!CLASS) R);
START!CODE
SKIPE 1,R;
HRRZ 1,(1);
END;
INTERNAL INTEGER PROCEDURE FLDTYPE(RPTR (ANY!CLASS) R;INTEGER IX);
RETURN($CLASS:TYPARR[$RECTYPE(R)][IX] LSH -23);
INTERNAL STRING SIMPLE PROCEDURE CVRCS(RPTR($CLASS) RC);
RETURN($CLASS:TXTARR[RC][0]);
INTERNAL STRING SIMPLE PROCEDURE CVRTS(INTEGER RT);
START!CODE
JRST CVRCS;
END;
INTERNAL INTEGER PROCEDURE FLDREF(RPTR(ANY!CLASS) R;STRING ID);
BEGIN
INTEGER I,N;
RPTR($CLASS) RC;
RC←$RECTYPE(R);
N←$CLASS:RECSIZ[RC];
FOR I←1 STEP 1 UNTIL N DO
IF EQU($CLASS:TXTARR[RC][I],ID) THEN
RETURN($CLASS:TYPARR[RC][I]+I+MEMORY[LOCATION(R)]);
RETURN(0);
END;
INTERNAL RPTR($CLASS) PROCEDURE CLSFND(STRING ID);
BEGIN
LABEL XIT;
RPTR($CLASS) RC;
MEMORY[LOCATION(RC)]←LOCATION($CLASS);
WHILE TRUE DO
BEGIN
IF EQU($CLASS:TXTARR[RC][0],ID) THEN
RETURN(RC)
ELSE
START!CODE
MOVE 1,RC;
HLRZ 1,-1(1);
CAIN 1,$CLASS;
JRST XIT;
MOVEM 1,RC;
END;
END;
XIT:RETURN(NULL!RECORD);
END;
INTERNAL RECORD!POINTER(ANY!CLASS) PROCEDURE BLDNRC(INTEGER RT);
START!CODE
! This procedure is to be called by a procedure of the form:
rptr(id) procedure new!id(fld1,...,fldn)
return(bldnew(loc(id))
;
EXTERNAL INTEGER $RECFN;
LABEL L1,L2;
SALACS;
SKIPN B,RT;
JRST 4,;
PUSH P,[1] ; ! allocate;
PUSH P,RT;
PUSHJ P,$RECFN;
HRRZ C,(A); ! record class;
MOVN C,3(C); ! - number of subfields;
JUMPE C,L2; ! no subfields;
HRRZ B,A; ! will do pushes to copy;
MOVE D,(RF); ! look at caller;
ADDI D,-1(C); ! point at first argument;
HRL D,C; ! -cnt,,first arg;
L1: PUSH B,(D); ! copy value;
SETZM (D); ! sterilize it;
AOBJN D,L1; ! iterate;
L2: END;
INTERNAL RPTR(ANY!CLASS) PROCEDURE CHKREC(RPTR(ANY!CLASS) R;INTEGER T);
BEGIN
IF T NEQ 0 AND RECTYPE(R) NEQ T THEN
BEGIN
USERERR(1,1,(CRLF&"RECORD ")&CVOS(MEMORY[LOCATION(R)])
&" HAS TYPE "&CVRTS(RECTYPE(R))&
" INSTEAD OF "&CVRTS(T));
END;
RETURN(R);
END;
INTERNAL RPTR(ANY!CLASS) PROCEDURE CPYREC(RPTR(ANY!CLASS) R1,R2(NULL!RECORD));
BEGIN
INTEGER I;
IF R2=NULL!RECORD THEN
R2←$REC$(ALLOCATE!RECORD,$RECTYPE(R1))
ELSE
CHKREC(R2,RECTYPE(R1));
FOR I←RECLEN(R1) STEP -1 UNTIL 1 DO
MEMORY[MEMORY[LOCATION(R2)]+I]←MEMORY[MEMORY[LOCATION(R1)]+I];
RETURN(R2);
END;
! cell routines;
INTERNAL RECORD!CLASS CELL(RPTR (ANY!CLASS) CAR,CDR);
INTERNAL RPTR(CELL) PROCEDURE CONS(RPTR(ANY!CLASS) A,D);
BEGIN
RPTR(CELL) C;
C←NEW!RECORD(CELL);
CELL:CAR[C]←A;
CELL:CDR[C]←D;
RETURN(C);
END;
INTERNAL RPTR(ANY!CLASS) RECURSIVE PROCEDURE SECOPY(RPTR(ANY!CLASS) C);
BEGIN
RPTR(CELL) L1,L2,L3;
IF C=NULL!RECORD THEN RETURN(NULL!RECORD);
IF RECTYPE(C) NEQ LOC(CELL) THEN RETURN(C);
DO BEGIN
L3←NEW!RECORD(CELL);
IF L1=NULL!RECORD THEN
L2←L1←L3
ELSE
BEGIN
CELL:CDR[L2]←L3;
L2←L3;
END;
CELL:CAR[L2]←SECOPY(CELL:CAR[C]);
C←CELL:CDR[C];
END UNTIL RECTYPE(C) NEQ LOC(CELL);
CELL:CDR[L2]←C;
RETURN(L1);
END;
INTERNAL BOOLEAN PROCEDURE IN!CL(RPTR(ANY!CLASS) C;RPTR(CELL) L);
BEGIN
WHILE L NEQ NULL!RECORD DO
BEGIN
IF C=CELL:CAR[L] THEN RETURN(TRUE);
L←CELL:CDR[L];
END;
RETURN(FALSE);
END;
INTERNAL RPTR(ANY!CLASS) PROCEDURE LLOP(REFERENCE RPTR(CELL) C);
BEGIN
RPTR(ANY!CLASS) V;
IF RECTYPE(C) NEQ LOCATION(CELL) THEN
BEGIN
USERERR(1,1,"LLOP CALLED WITH RECORD OF TYPE "&CVRTS(RECTYPE(C)));
RETURN(NULL!RECORD);
END;
V←CELL:CAR[C];
C←CELL:CDR[C];
RETURN(V);
END;
INTERNAL INTEGER PROCEDURE CL!LEN(RPTR(CELL) C);
BEGIN
INTEGER I;
I←0;
WHILE C NEQ NULL DO
BEGIN
I←I+1;
C←CELL:CDR[C];
END;
RETURN(I);
END;
INTERNAL RPTR(CELL) PROCEDURE APPEND(RPTR(CELL) ARG1, ARG2);
BEGIN "append" ! Coded by RF;
! Appends the two lists by RPLACD on the last CDR field of ARG1;
RPTR(CELL) P1, P2;
IF ARG1 = NULL!RECORD THEN RETURN(ARG2);
P1 ← ARG1;
WHILE P1 NEQ NULL!RECORD DO
BEGIN ! Chain down ARG1 looking for the end;
P2 ← P1;
P1 ← CELL:CDR[P1];
END;
CELL:CDR[P2] ← ARG2;
RETURN(ARG1);
END "append";
INTERNAL RPTR(CELL) PROCEDURE LIST2(RPTR(ANY!CLASS) C1,C2);
RETURN(CONS(C1,CONS(C2,NULL!RECORD)));
INTERNAL RPTR(ANY!CLASS) PROCEDURE CONSON(RPTR(ANY!CLASS) X;REFERENCE RPTR(CELL) C);
BEGIN
C←CONS(X,C);
RETURN(X);
END;
! rlist primitives;
INTERNAL RECORD!CLASS RLIST(INTEGER LEN;RPTR(CELL) FIRST,LAST);
INTERNAL PROCEDURE RLADD(RPTR(RLIST) RL;RPTR(ANY!CLASS) REC;INTEGER N);
BEGIN
! adds REC to RL after N;
INTEGER I,L;
RPTR(CELL) C1;
L←RLIST:LEN[RL];
IF N>L OR N<0 THEN
BEGIN
BUG("RLADD INDEX OUT OF RANGE:"&CVS(N));
N←L;
END;
IF N=L THEN
BEGIN
IF N=0 THEN
RLIST:FIRST[RL]←RLIST:LAST[RL]←CONS(REC,NULL!RECORD)
ELSE
BEGIN
C1←CONS(REC,NULL!RECORD);
CELL:CDR[RLIST:LAST[RL]]←C1;
RLIST:LAST[RL]←C1;
END;
END
ELSE IF N=0 THEN
RLIST:FIRST[RL]←CONS(REC,RLIST:FIRST[RL])
ELSE
BEGIN
C1←RLIST:FIRST[RL];
FOR I←2 STEP 1 UNTIL N DO C1←CELL:CDR[C1];
CELL:CDR[C1]←CONS(REC,CELL:CDR[C1]);
END;
RLIST:LEN[RL]←L+1;
END;
INTERNAL INTEGER PROCEDURE RLREM(RPTR(RLIST) RL;RPTR(ANY!CLASS) REC;
INTEGER HOWMANY(1));
BEGIN
! Removes up to the first HOWMANY instances of REC from RL.
Returns the number actually removed.
;
INTEGER CNT;
RPTR(CELL) C,CP;
CNT←0;
C←RLIST:FIRST[RL];CP←NULL!RECORD;
WHILE C NEQ NULL!RECORD AND HOWMANY>0 DO
BEGIN
IF REC=CELL:CAR[C] THEN
BEGIN
C←CELL:CDR[C];
IF CP NEQ NULL!RECORD THEN
CELL:CDR[CP]←C
ELSE
RLIST:FIRST[RL]←C;
RLIST:LEN[RL]←RLIST:LEN[RL]-1;
HOWMANY←HOWMANY-1;
CNT←CNT+1;
IF C=NULL!RECORD THEN
RLIST:LAST[RL]←CP;
END
ELSE
BEGIN
CP←C;C←CELL:CDR[C];
END;
END;
RETURN(CNT);
END;
INTERNAL RPTR(ANY!CLASS) PROCEDURE RLNREM(RPTR(RLIST) RL;INTEGER N);
BEGIN
! removes RL[N] from RL & returns it;
INTEGER I;
IF 1 LEQ N LEQ RLIST:LEN[RL] THEN
BEGIN
RPTR(ANY!CLASS) REC;
RPTR(CELL) C,CP;
C←RLIST:FIRST[RL];CP←NULL!RECORD;
FOR I←2 STEP 1 UNTIL N DO
BEGIN
CP←C;C←CELL:CDR[C];
END;
REC←CELL:CAR[C];C←CELL:CDR[C];
IF N=1 THEN
RLIST:FIRST[RL]←C
ELSE
CELL:CDR[CP]←C;
IF C=NULL!RECORD THEN
RLIST:LAST[RL]←CP;
RLIST:LEN[RL]←RLIST:LEN[RL]-1;
RETURN(REC);
END;
BUG("RLNREM OUT OF RANGE: "&CVS(N));
RETURN(NULL!RECORD);
END;
INTERNAL INTEGER PROCEDURE RLINX(RPTR(RLIST) RL;RPTR(ANY!CLASS) REC);
BEGIN
! returns index of REC in RL.;
INTEGER I;RPTR(CELL) C;
C←RLIST:FIRST[RL];
FOR I←1 STEP 1 UNTIL RLIST:LEN[RL] DO
BEGIN
IF REC=CELL:CAR[C] THEN RETURN(I);
C←CELL:CDR[C];
END;
RETURN(0);
END;
INTERNAL RPTR(ANY!CLASS) PROCEDURE RLNTH(RPTR(RLIST) RL;INTEGER N);
BEGIN
! returns the N'th element of RL.;
IF 1 LEQ N LEQ RLIST:LEN[RL] THEN
BEGIN
RPTR(CELL) C;
C←RLIST:FIRST[RL];
WHILE (N←N-1)>0 DO C←CELL:CDR[C];
RETURN(CELL:CAR[C]);
END
ELSE
BEGIN
BUG("RLNTH OUT OF RANGE: "&CVS(N));
RETURN(NULL!RECORD);
END;
END;
INTERNAL RPTR(RLIST) PROCEDURE RLCOPY(RPTR(RLIST) RL,RL2(NULL!RECORD));
BEGIN
! copies RL into RL2 & returns the copy.;
RPTR(CELL) C;
INTEGER L,I;
IF RL2=NULL!RECORD THEN
RL2←NEW!RECORD(RLIST)
ELSE
BEGIN
RLIST:FIRST[RL2]←RLIST:LAST[RL2]←NULL!RECORD;
RLIST:LEN[RL]←0;
END;
L←RLIST:LEN[RL]-1;
C←RLIST:FIRST[RL];
FOR I←0 STEP 1 UNTIL L DO
BEGIN
RLADD(RL2,CELL:CAR[C],I);
C←CELL:CDR[C];
END;
END;
INTERNAL MATCHING RECPROC MAPRLIST(RPTR(RLIST) RL;REFERENCE RPTR(ANY!CLASS) R);
BEGIN
EXTERNAL RPTR(ANY!CLASS) PROCEDURE $REC$(INTEGER OP;RPTR(ANY!CLASS) R);
RPTR(CELL) C,CP;
RPTR(RLIST) RL1;
PROCEDURE RL1KILL;
BEGIN
WHILE C NEQ NULL!RECORD DO
BEGIN
CP←C;
C←CELL:CDR[C];
$REC$(DELETE!RECORD,C);
END;
RL1←RL1; ! access bug;
$REC$(DELETE!RECORD,RL1);
END;
CLEANUP RL1KILL;
RL1←RLCOPY(RL);
C←RLIST:FIRST[RL1];
WHILE C NEQ NULL!RECORD DO
BEGIN
R←CELL:CAR[C];CP←C;C←CELL:CDR[C];
$REC$(DELETE!RECORD,CP);
SUCCEED;
END;
FAIL;
END;
END "RECAUX"